import * as _ from "lodash"
import { camelCase, snakeCase } from "../case"
import { OptionSelection } from "../catalog"
import httpClient from "../httpclient"

export class Cart {
  public id: string
  public items: CartItem[] = []

  constructor(id?: string, items?: CartItem[]) {
    if (id) {
      this.id = id
    }
    if (items) {
      this.items = items
    }
  }
}

export class CartItem {
  public id: string
  public storeId: string
  public productId: string
  public variantId: string
  public quantity: number
  public price: number
  public name: string
  public optionSelections: OptionSelection[] = []
  public imageUrl: string
  public checked: boolean
  public addedTime: string
}

export class CartItemAdjustment {
  public itemId: string
  public productId: string
  public variantId: string
  public quantityDelta: number
}

export class CartServiceV1 {

  public static getCart(cartId: string): Promise<Cart> {
    return httpClient.get(`/v1/carts/${cartId}`)
      .then(({ data }) => data)
      .then(camelCase)
      .then(data => {
        return data
          ? new Cart(data.id, _.map(data.items, item => _.assign(new CartItem(), item)))
          : new Cart(cartId, [])
      })
  }

  public static checkCartItem(cart: string, itemId: string): Promise<void> {
    return httpClient.post(`/v1/carts/${cart}/items/${itemId}/check`)
      .then(({ data }) => data).then(camelCase)
  }

  public static updateCartItem(cart: string, item: CartItem): Promise<void> {
    return httpClient.patch(`/v1/carts/${cart}/items/${item.id}`, snakeCase(item))
      .then(({ data }) => data).then(camelCase)
  }

  public static adjustCartItem(cart: string, adjustment: CartItemAdjustment): Promise<void> {
    const url = _.isEmpty(adjustment.itemId)
      ? `/v1/carts/${cart}/items/adjust`
      : `/v1/carts/${cart}/items/${adjustment.itemId}/adjust`
    return httpClient.post(url, snakeCase(adjustment))
      .then(({ data }) => data).then(camelCase)
  }

  public static uncheckCartItem(cart: string, itemId: string): Promise<void> {
    return httpClient.post(`/v1/carts/${cart}/items/${itemId}/uncheck`)
      .then(({ data }) => data).then(camelCase)
  }

  public static checkCartItems(cart: string, itemIds: string[]): Promise<void> {
    return httpClient.post(`/v1/carts/${cart}/items/check/batch`, itemIds)
      .then(({ data }) => data).then(camelCase)
  }

  public static uncheckCartItems(cart: string, itemIds: string[]): Promise<void> {
    return httpClient.post(`/v1/carts/${cart}/items/uncheck/batch`, itemIds)
      .then(({ data }) => data).then(camelCase)
  }

  public static checkAllCartItems(cart: string): Promise<void> {
    return httpClient.post(`/v1/carts/${cart}/items/check`)
      .then(({ data }) => data).then(camelCase)
  }

  public static uncheckAllCartItems(cart: string): Promise<void> {
    return httpClient.post(`/v1/carts/${cart}/items/uncheck`)
      .then(({ data }) => data).then(camelCase)
  }

  public static addCartItem(cart: string, item: CartItem): Promise<void> {
    return httpClient.post(`/v1/carts/${cart}/items`, snakeCase(item))
      .then(({ data }) => data).then(camelCase)
  }

  public static addCartItems(cart: string, items: CartItem[]): Promise<void> {
    return httpClient.post(`/v1/carts/${cart}/items/batch`, snakeCase(items))
      .then(({ data }) => data).then(camelCase)
  }

  public static removeCartItems(cart: string, itemIds: string[]): Promise<void> {
    return httpClient.delete(`/v1/carts/${cart}/items/batch`, { data: itemIds })
      .then(({ data }) => data).then(camelCase)
  }
}
